Objektumok használata ORACLE-ben

Objektumok használata hasonló okokból ajánlott, mint minden más fejlesztői környezetben. A sok egyéb előnye mellett komplexebb, többször felhasználható komponenseket készíthetünk. Emellett kívülről, pl. egy JAVA nyelven megírt alkalmazásból egy Oracle objektumot (annak attribútumait vagy eljárásait) könnyen meg lehet hívni. Továbbá az objektumok használata a teljesítményt is fokozza, ahogy lentebb látni fogjuk, például egy collection-be helyezve az objektumokat elemeit, a memóriában futtatva jóval gyorsabban tudunk egy folyamatot lefuttatni, mintha direkt táblából olvasnánk, vagy temp táblába ínánk.

Pár példa a használatára:

Hasznos tud lenni az adatbázisok létrehozásakor. Ha például több adatbázis táblában szeretnénk ugyanolyan mezőket eltárolni (pl. a customers tábla egyéb adatok mellett a vásárlók címét, irányítószámát tartalmazza, ugyanígy a vendor tábla egyebek mellett a telephelyek címét, irányítószámát tartalmazza), akkor a táblák létrehozásakor elegendő az objektumot meghivatkozni:

create or replace type address as object (

Streetno varchar2(20),

City varchar2(20),

ZIP varchar2(20));



create table vendors (vendor_name varchar2(20),

Vendor_addr address);



create table customers (customer_name varchar2(20),

Customer_addr address);
Egy új objektum létrehozását többek között a következő módon tudjuk megtenni. A fentebb létrehozott address-ből konstruktor használatával (ahol a konstruktornak átadjuk az értékeket, amely értékekkel az új objektumot létrehozzuk):
DECLARE

v_address address;

BEGIN

v_address := address('Fő utca', 'Budapest', '2024');

DBMS_OUTPUT.PUT_LINE(v_address.Streetno || ', ' || v_address.City || ', ' || v_address.ZIP);

END;
Object Type létrehozásakor nem csak a fenti példában látható attribútumokat hozhatunk létre, hanem metódusokat is, amelyek az objektum létrehozásakor futnak le attól függően, hogy milyen értékeket adunk át neki. Az alábbiban egy CONSTRUCTOR FUNCTION-t hozunk létre, ahol egy üres konstruktort hozunk létre - ennek eredményeképpen egy üres objektumot kapunk aztán vissza:
create or replace type address as object (

Streetno varchar2(20),

City varchar2(20),

ZIP varchar2(20),

CONSTRUCTOR FUNCTION address

RETURN SELF AS RESULT );
Ehhez kapcsolódóan létre kell hoznunk a TYPE BODY-t is, ahol az objektum eljárásait kell definiálnunk:
create or replace type body address AS

CONSTRUCTOR FUNCTION address

RETURN SELF AS RESULT

AS BEGIN

RETURN;

END;

END;
Egy új objektumot úgy tudunk ebből létrehozni, hogy a konstruktornak nem adunk át értéket, viszont az értékeket manuálisan hozzuk létre:
DECLARE

v_address address := address();

BEGIN

v_address.Streetno : = 'Fő utca';

v_address.City := 'Budapest';

v_address.ZIP := '1024';

DBMS_OUTPUT.PUT_LINE(v_address.Streetno || ', ' || v_address.City || ', ' || v_address.ZIP);

END;
Az alábbiakban a fentit kiegészítjük, itt már átadunk a konstruktornak értékeket, és az annak átadott értéket kapja meg az új objektum:
create or replace type address as object (

Streetno varchar2(20),

City varchar2(20),

ZIP varchar2(20),

CONSTRUCTOR FUNCTION address

RETURN SELF AS RESULT

CONSTRUCTOR FUNCTION address(Streetno VARCHAR2, City varchar2, ZIP varchar2)

RETURN SELF AS RESULT );



create or replace type body address AS

CONSTRUCTOR FUNCTION address

RETURN SELF AS RESULT

AS BEGIN

RETURN;

END;

CONSTRUCTOR FUNCTION address (Streetno VARCHAR2, City varchar2, ZIP varchar2)

RETURN SELF AS RESULT

AS BEGIN

SELF.Streetno := Streetno;

SELF.City := City;

SELF.ZIP := ZIP;

RETURN;

END;

END;



DECLARE

v_address address := address('Fő utca', 'Budapest', '1024');

BEGIN

DBMS_OUTPUT.PUT_LINE(v_address.Streetno || ', ' || v_address.City || ', ' || v_address.ZIP);

END;
Amiben nagyon hasznos tud lenni az object type, az a COLLECTION-ök használata. Egy collection-ben el tudjuk tárolni a létrehozott objektumokat, amelyet aztán könnyen ki tudunk iratni, vagy be tudjuk tenni egy adattáblába, vagy más műveleteket tudunk rajtuk futtatni. Ezzel a módszerrel sokkal gyorsabban tudunk végigmenni az adatokon, mintha adattáblából kérdeznénk le azokat. Első körben hozzunk létre egy collection-t a fenti objektumból:
CREATE OR REPLACE TYPE address_a AS TABLE OF address;
Ezzel létrehoztunk egy collection-t, amiben az address objektumok értékeit fogjuk eltárolni.
DECLARE

v_address_a address_a := address_a();

BEGIN

v_address_a.EXTEND; -- ezzel létrehozunk egy új elemet a collection-ben

v_address_a(1) := address('Fő utca', 'Budapest', '1024'); -- az első elem értékei

v_address_a.EXTEND; -- ezzel létrehozunk egy második elemet a collection-ben

v_address_a(2) := address('Alsó utca', 'Érd', '2030'); -- a második elem értékei

END;
Ezzel létrehoztunk két objektumot, azokat eltároltuk a collection-ben. Hatékony módszer a BULK COLLECT INTO-val való történő beolvasás a collection-be:
DECLARE

v_address_a address_a;

BEGIN

SELECT address(Streetno, City, ZIP)

BULK COLLECT INTO v_address_a

FROM table_address;

END;
A collection tartalmára aztán egyéb üzleti feldolgozást lehet építeni. Még egy példa a teljes folyamatra:

1. lépésben collection létrehozása (ide tesszük majd be az objektumok elemeit):
DECLARE

create or replace TYPE "OUT_TYPE" AS table of NUMBER(20,5);
2. lépésben: OBJECT TYPE és OBJECT TYPE BODY létrehozása, ezzel hozzuk majd létre magukat az objektumokat:
DECLARE

create or replace TYPE "J_SZEKT_SEMAMUTATOK" AS OBJECT (

P_11 NUMBER(20,0),

P_118 NUMBER(20,0),

STATIC FUNCTION getNull(J_SEMA J_SZEKT_SEMAMUTATOK)

RETURN J_SZEKT_SEMAMUTATOK );



create or replace TYPE BODY "J_SZEKT_SEMAMUTATOK" AS

STATIC FUNCTION getNull(J_SEMA J_SZEKT_SEMAMUTATOK)

RETURN J_SZEKT_SEMAMUTATOK AS v_j J_SZEKT_SEMAMUTATOK;

BEGIN

v_j:=J_SZEKT_SEMAMUTATOK

(0,-- P_11 ,

0,-- P_118 ); -- itt adunk alapvetően 0 értékeket minden mezőnek

RETURN v_j;

END getNull;

END;
3. lépésben egy eljárásban meghívjuk az OBJECT TYPE-ot:
create or replace PACKAGE BODY "J_A_HITEL_T" as

v_j j_szekt_semamutatok;

PROCEDURE HITELINTEZET AS

BEGIN

v_j := j_szekt_semamutatok.getnull(v_j); --első körben a getNull funnction: minden mező 0 értéket kap

-- innentől pedig minden attribútumnak kiszámítunk egy értéket üzleti logika szerint:

v_j.p_11 := 256;

J_SZEKT_EVES_T.FELTOLT('P_11', v_j.p_11);

v_j.p_118 := v_j.p_11 * 3.14;

J_SZEKT_EVES_T.FELTOLT('P_118', v_j.p_118);
4. lépésben a folyamat elején létrehozott collection-be beillesztjük az objektumokat:
PROCEDURE FELTOLT (v_mutato_nev VARCHAR2, v_ertek NUMBER) AS

BEGIN

v1.extend(2); -- 2 db. mutatót hoztunk létre az OBJECT TYPE-ban

v1(v_mutato_nev) := v_ertek;

END;
5.lépésben a collection elemeit végül egy táblába betöltjük
PROCEDURE FELTOLT_TABLABA AS

BEGIN

v1.extend(2);

FOR i IN 1..c_db LOOP

INSERT INTO table_name VALUES (v1(i));

END LOOP;

END;
Nagy vonakakban az objektumokról ennyi, persze még millió lehetőség rejlik benne, de ha a gyorsaságot, egyszerűséget tartjuk szem előtt, akkor ezekkel az alapokkal már el lehet boldogulni.